using System;
using System.Collections.Generic;
using System.Text;
using Index;
using Index.PostingLists;
using Index.PostingLists.Entry;

namespace Query.Queries
{
    // zapytania typu : wiki matematyka twierdzenie
    // w modelu wektorowym (uproszczonym)
    public class FreeTextQuery
    {
        public class DocumentWithScore : IComparable<DocumentWithScore>
        {
            public int doc_id;
            public double score;

            public DocumentWithScore(int doc_id, double score)
            {
                this.doc_id = doc_id;
                this.score = score;
            }


            public int CompareTo(DocumentWithScore other)
            {
                if (other.score > this.score)
                {
                    return 1;
                }

                if (other.score < this.score)
                {
                    return 1;
                }

                return 0;

            }

        }

        private WikiIndex index;

        public FreeTextQuery(WikiIndex index)
        {
            this.index = index;
        }

        public double IDf(string word)
        {
            int df = index.DocumentFrequency(word);

            if (df == 0)
            {
                return 0;
            }
            return Math.Log(index.N / df);
        }

        public int[] SelectDocuments(string[] query, int K)
        {
            Dictionary<int, double> score = new Dictionary<int, double>();

            #region selectdocuments

            for (int i = 0; i < query.Length; i++)
            {
                object o = index.GetPostingList(query[i]);

                if (o != null)
                {

                    if (index.Config.IndexType == IndexType.Positional)
                    {
                        DocumentPositionList list = (DocumentPositionList)o;

                        foreach (PositionEntry entry in list)
                        {

                            if (score.ContainsKey(entry.DocumentId))
                            {
                                score[entry.DocumentId] += entry.Freq * IDf(query[i]);
                            }
                            else
                            {
                                score[entry.DocumentId] = entry.Freq * IDf(query[i]);
                            }
                        }
                    }

                    if (index.Config.IndexType == IndexType.Frequencial)
                    {

                        DocumentFrequencyList list = (DocumentFrequencyList)o;

                        foreach (FrequencyEntry entry in list)
                        {

                            if (score.ContainsKey(entry.DocumentId))
                            {
                                score[entry.DocumentId] += entry.Freq * IDf(query[i]);
                            }
                            else
                            {
                                score[entry.DocumentId] = entry.Freq * IDf(query[i]);
                            }
                        }


                    }

                }

            }
            #endregion

            #region convert to array
            List<DocumentWithScore> docs = new List<DocumentWithScore>();
           

            foreach (KeyValuePair<int, double> item in score)
            {
                docs.Add(new DocumentWithScore(item.Key, item.Value));
            }
           

            DocumentWithScore[] array = docs.ToArray();
            Array.Sort<DocumentWithScore>(array);

            List<int> result = new List<int>();

            for (int i = 0; (i < array.Length) && (i < K); i++)
            {
                //Console.WriteLine("Score : {0} Doc: {1}", array[i].score, index.GetURLToDocument(array[i].doc_id));
                result.Add(array[i].doc_id);
            }

            #endregion

            return result.ToArray();
        }
    }
}